<script>
import { computed, defineComponent, onBeforeUnmount, ref, watch } from 'vue';
import { createNamespace, transformStyleSize, parseTimeData } from '../utils';
import { isSameSecond, raf, cancelRaf } from './util';

export default defineComponent({
  name: createNamespace('CountDown')[0],
  options: {
    // https://uniapp.dcloud.io/matter.html#mp
    virtualHost: true,
  },
  props: {
    // 毫秒时间戳
    time: {
      type: [String, Number],
    },
    autoStart: {
      type: Boolean,
      default: true,
    },
    // 默认 时分秒，可以指定一个统一的分隔符，TODO: 分别指定
    separator: {
      type: String,
    },
    daySeparator: {
      type: [String, Object],
    },
    separatorStyle: {
      type: String,
    },
    blockStyle: {
      type: String,
    },
    // 要天不
    day: {
      type: Boolean,
      default: false,
    },
    hour: {
      type: Boolean,
      default: true,
    },
    minute: {
      type: Boolean,
      default: true,
    },
    // 要毫秒不
    millisecond: {
      type: [Boolean, String],
      default: false,
    },
    // 毫秒前面加0
    doubleDigitMill: {
      type: Boolean,
      default: false,
    },
  },
  emits: ['finish'],
  setup(props, context) {
    const theBlockStyle = computed(() => transformStyleSize(props.blockStyle));
    const theSepStyle = computed(() =>
      transformStyleSize(props.separatorStyle),
    );

    let tid;
    let counting;
    let remain = 0;
    let endTime = 0;
    const timeData = ref(parseTimeData(0));

    // 暂停
    const pause = () => {
      counting = false;
      cancelRaf(tid);
    };
    const setRemain = (value) => {
      remain = value;
      timeData.value = parseTimeData(value, props.day);

      if (value === 0) {
        pause();
        context.emit('finish');
      }
    };
    const getRemain = () => {
      return Math.max(endTime - Date.now(), 0);
    };
    const microTick = () => {
      tid = raf(() => {
        setRemain(getRemain());

        if (remain !== 0) {
          microTick();
        }
      });
    };
    const macroTick = () => {
      tid = raf(() => {
        const value = getRemain();

        if (!isSameSecond(value, remain) || value === 0) {
          setRemain(value);
        }

        if (remain !== 0) {
          macroTick();
        }
      });
    };
    const tick = () => {
      props.millisecond ? microTick() : macroTick();
    };
    // 开始
    const start = () => {
      if (counting) return;

      counting = true;
      endTime = Date.now() + remain;
      tick();
    };
    // 重置
    const reset = () => {
      pause();
      if (!props.time) return;
      remain = props.time;
      setRemain(remain);

      props.autoStart && start();
    };

    watch(() => props.time, reset, { immediate: true });
    onBeforeUnmount(() => {
      cancelRaf(tid);
      tid = null;
    });

    return { theBlockStyle, theSepStyle, timeData, reset };
  },
});
</script>

<template>
  <div class="fan-flex fan-align-center fan-count-down">
    <template v-if="day">
      <div :style="theBlockStyle" class="fan-count-down__block">
        {{ timeData.days }}
      </div>
      <div :style="theSepStyle" class="fan-count-down__sep">
        {{ daySeparator ? daySeparator : '天' }}
      </div>
    </template>
    <template v-if="hour">
      <div :style="theBlockStyle" class="fan-count-down__block">
        {{ timeData.hours }}
      </div>
      <div :style="theSepStyle" class="fan-count-down__sep">
        {{ separator ? separator : '时' }}
      </div>
    </template>
    <template v-if="minute">
      <div :style="theBlockStyle" class="fan-count-down__block">
        {{ timeData.minutes }}
      </div>
      <div :style="theSepStyle" class="fan-count-down__sep">
        {{ separator ? separator : '分' }}
      </div>
    </template>
    <div :style="theBlockStyle" class="fan-count-down__block">
      {{ timeData.seconds }}
    </div>
    <div v-if="millisecond || !separator" :style="theSepStyle" class="fan-count-down__sep">
      {{ separator ? separator : '秒' }}
    </div>
    <div v-if="millisecond" :style="theBlockStyle" class="fan-count-down__block">
      {{ doubleDigitMill ? '0' : '' }}{{ timeData.milliseconds }}
    </div>
  </div>
</template>
